// Bootstrap Jx
 (function(GLOBAL, O, A){

	var J = GLOBAL.Jx = { "GLOBAL": GLOBAL };

	// fixed global "undefined" var name
 	if (!('undefined' in J.GLOBAL) || J.GLOBAL['undefined'] !== void(0)){

		J.GLOBAL['undefined'] = void(0);

	}

	// Array Fixes
	//-- fix array that doesn't support indexOf
	if (!Array.prototype.indexOf){

		Array.prototype.indexOf = function(o, from){

			var my = this,

				l = my.length;

			from = J.isNumber(from) ?

					from

					:

					0;

			from = (from < 0) ?

				Math.ceil(from)

				:

				Math.floor(from);

			if (from < 0){

				from += l;

			}

			for (; from < l; from++) {

				if ( (from in my) && (my[from] === o) ){

					return from;

				}
			}

			return -1;

		}
	}

	if (!Array.prototype.lastIndexOf){

		Array.prototype.lastIndexOf = function(o, from){

			var my = this,

				l = my.length;

			if (J.isNumber(from)){

				from = (from < 0) ?

					Math.ceil(from)

					:

					Math.floor(from);

				if (from < 0) {

					from += l;

				} else if (from >= l){

					from = l - 1;

				}
			} else {

				from = l - 1;

			}


			for (; from > -1; from--) {

				if ((from in my) && (my[from] === o)){

					return from;

				}

			}

			return -1;
		};


	}

	// Production steps of ECMA-262, Edition 5, 15.4.4.18
	if (!Array.prototype.forEach){

		Array.prototype.forEach = function(fn, scope){

			var T,

				o = Object(this);

			if (!J.isFunction(fn)) {

				throw new TypeError();

			}

			if ( scope ) {

				T = scope;

			}

			for(var c=0, l = o.length >>> 0, name; c < l; c++) {

				if (c in o){

					fn.call( T, o[c], c, o );

				}

			}

		};

	}


	// create helpers
	J._ = {

		enumerables: (function(prop){

			var isEnumerable = O.propertyIsEnumerable,

				flags = {};

			for(var n, o = {}, l = prop.length; l--;){

				o[ n = prop[l] ] = 'n';

				if (isEnumerable.call(o, n)){

					flags[n] = false;

					prop.splice(l, 1);

				} else {

					flags[n] = false;

				}

			}

			prop.flags = flags;

			return prop;

		})([ 'hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor' ]),

		helper_EachObject: function(o, fn, scope){

			scope = scope || null;

			var ObjProto = O,

				n;

			for(n in o){

				if (fn.call(scope, n, o[n], o) === false){

					break;

				}

			}

			if (o instanceof ObjProto.constructor){

				for(var hasOwn = ObjProto.hasOwnProperty, enums = J._.enumerables, l = enums.length; l--;){

					n = enums[l];

					if ((hasOwn.call(o, n) || o[n] !== ObjProto[n]) &&

						fn.call(scope, n, o[n], o) === false

					){

						break;

					}

				}

			}

			return o;

		},

		helper_AssignIfObject: function(name, value){

			if (!(name in this) || typeof this[name] == 'undefined'){

				this[name] = value;

			}

		},

		helper_AssignObject: function(name, value, obj){

			this[name] = value;

		},

		helper_AssignObject_Clear: function(name, value, obj){

			this[name] = value;

			Jx._.helper_ClearObjectProperties(name, value, obj);

		},

		helper_AssignObjectModifiedProperty: function(name, value, obj){

			if (O.hasOwnProperty.call(obj, name)){

				this[name] = value;

			}

		},

		helper_AssignObjectModifiedProperty_Clear: function(name, value, obj){

			if (O.hasOwnProperty.call(obj, name)){

				this[name] = value;

			}

			Jx._.helper_ClearObjectProperties(name, value, obj);

		},

		helper_AssignIfOwnObject: function(name, value, obj){

			if (O.hasOwnProperty.call(obj, name)){

				Jx._.helper_AssignIfObject.call(this, name, value, obj);

			}

		},

		helper_AssignIfOwnObject_Clear: function(name, value, obj){

			var _ = Jx._;

			if (O.hasOwnProperty.call(obj, name)){

				_.helper_AssignIfObject.call(this, name, value, obj);

			}

			_.helper_ClearObjectProperties(name, value, obj);

		},

		helper_ClearObjectProperties: function(name, value, obj){

			if (O.hasOwnProperty.call(obj, name)){

				delete obj[name];

			}

		}

	};

	// basic object assignment
	J._.helper_EachObject({

		each: J._.helper_EachObject,

		assign: function(o1, o2, clear){

			var J = Jx;

			J.each( o2,

				J._[

					 clear ?

						'helper_AssignObject_Clear'

						:

						'helper_AssignObject'

				],

				o1

			);

			return o1;

		},

		assignOwned: function(o1, o2, clear){

			var J = Jx;

			J.each(o2,

				J._[

					clear ?

						'helper_AssignObjectModifiedProperty_Clear'

						:

						'helper_AssignObjectModifiedProperty'

				], o1

			);

			return o1;

		},

		assignIf: function(o1, o2, owned, clear){

			var J = Jx;

			J.each(o2,

				J._[

					owned === true && owned instanceof Object ?

						clear ?

							'helper_AssignIfOwnObject_Clear'

							:

							'helper_AssignIfOwnObject'

						:

						clear ?

							'helper_AssignIfObject_Clear'

							:

							'helper_AssignIfObject'

				],

				o1

			);

			return o1;

		},

		clearObject: function(o){

			var J = Jx;

			if (J.isArray(o)){

				o.splice(0, o.length);

			} else if (J.isObject(o)){

				J.each(o, J._.helper_ClearObjectProperties);

			}

			return o;

		},

		destruct: function(){

			var Jx = J,

				objs = arguments;

			for(var obj, c=-1, l = objs.length; l--;){

				obj = objs[++c];

				if (obj instanceof Object){

					if (J.isFunction(obj.destroy)){

						obj.destroy();

					} else {

						J.clearObject(obj);

					}

				}

			}

		}

	}, J._.helper_AssignObject, J);

})(

   (function(){ return this; })(),

   Object.prototype,

   Array.prototype

);



/**
 * Jx Utility Methods
 */
 Jx.assign( Jx, {

	isObject: function(o, nativeObject){

		var type = typeof o,

			O = Object;

		return o != null && (

			nativeObject !== false ?

				O.prototype.toString.call(o) == '[object Object]' && o instanceof O

				:

				type == 'object' || type == 'function'

		);

	},

	isString: function(o, notEmpty){

		return Object.prototype.toString.call(o) == '[object String]' &&

			(notEmpty !== true || !!o);

	},

	isBoolean: function(o){

		return Object.prototype.toString.call(o) == '[object Boolean]';

	},

	isNumber: function(o){

		return Object.prototype.toString.call(o) == '[object Number]' && isFinite(o);

	},

	isScalar: function(o, includeBoolean){

		var type = Object.prototype.toString.call(o);

		return type == '[object String]' ||

			(type == '[object Number]' && isFinite(o)) ||

			(!!includeBoolean && type == '[object Boolean]');

	},

	isFunction: function(o){

		return Object.prototype.toString.call(o) == '[object Function]';

	},

	isArray: function(o, notEmpty){

		return Object.prototype.toString.call(o) == '[object Array]' &&

			(notEmpty !== true || !!o.length);

	},

	isDate: function(o){

		return Object.prototype.toString.call(o) == '[object Date]';

	},

	isRegExp: function(o){

		return Object.prototype.toString.call(o) == '[object RegExp]';

	},

	isSignature: function(o, signature){

		return Object.prototype.toString.call(o) == '[object '+String(signature)+']';

	},

	isPropertyEnumerable: function(access, o){

		var O = Object.prototype,

			enumerables = Jx._.enumerables.flags;

		if (O.propertyIsEnumerable.call(o, access) || O.hasOwnProperty.call(o, access)){

			return true;

		} else if (access in enumerables && o instanceof Object){

			return access in o &&

				o[access] !== O[access];

		}

		return false;

	},

	createError: function(type){

		var GLOBAL = Jx.GLOBAL,

			Class = Error,

			messageIndex = arguments.length > 1 ?

				1

				:

				0;

		if (messageIndex){

			var camelized;

			if (Jx.isString(type, true) &&

				(camelized = type.charAt(0).toUpperCase() + type.substring(1, type.length) + 'Error') in GLOBAL

			){

				Class = GLOBAL[camelized];

			} else {

				messageIndex = 0;

			}

		}

		var message = Array.prototype.slice.call(arguments, messageIndex).join(' ');

		return new Class(message);

	},

	getErrorClass: function(type){

		var GLOBAL = Jx.GLOBAL,

			Class = Error,

			camelized;

		if (Jx.isString(type, true) &&

			(camelized = type.charAt(0).toUpperCase() + type.substring(1, type.length) + 'Error') in GLOBAL

		){

			Class = GLOBAL[camelized];

		}

		return Class;

	}

});
